﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Reflection.Emit;
using System.Reflection;
using System.ComponentModel;
using System.IO;

namespace Bronze.XXT.PhoneServer
{
    public static class Extension
    {
        public static void UpdateUI(this Control control, MethodInvoker method)
        {
            if (control.InvokeRequired)
            {
                control.Invoke(method);
            }
            else
            {
                method();
            }
        }

       

        public static T Copy<T>(this T source) where T : new()
        {
            T newObj = new T();
            PropertyInfo[] fieldInfoArray = source.GetType().GetProperties(
                BindingFlags.Instance | BindingFlags.Public |
                BindingFlags.SetProperty | BindingFlags.DeclaredOnly);
            foreach (PropertyInfo fieldInfo in fieldInfoArray)
            {
                if (fieldInfo.PropertyType.IsValueType || fieldInfo.PropertyType == typeof(string))
                {
                    try
                    {
                        object sourceFieldValue = fieldInfo.GetValue(source, null);
                        fieldInfo.SetValue(newObj, sourceFieldValue, null);
                    }
                    catch (System.Exception ex)
                    {

                    }

                }
            }
            return newObj;
        }


        public static object ChangeType(this object value, Type conversionType)
        {
            // Note: This if block was taken from Convert.ChangeType as is, and is needed here since we're
            // checking properties on conversionType below.
            if (conversionType == null)
            {
                throw new ArgumentNullException("conversionType");
            } // end if

            // If it's not a nullable type, just pass through the parameters to Convert.ChangeType

            if (conversionType.IsGenericType &&
              conversionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>)))
            {
                // It's a nullable type, so instead of calling Convert.ChangeType directly which would throw a
                // InvalidCastException (per http://weblogs.asp.net/pjohnson/archive/2006/02/07/437631.aspx),
                // determine what the underlying type is
                // If it's null, it won't convert to the underlying type, but that's fine since nulls don't really
                // have a type--so just return null
                // Note: We only do this check if we're converting to a nullable type, since doing it outside
                // would diverge from Convert.ChangeType's behavior, which throws an InvalidCastException if
                // value is null and conversionType is a value type.
                if (value == null)
                {
                    return null;
                } // end if

                // It's a nullable type, and not null, so that means it can be converted to its underlying type,
                // so overwrite the passed-in conversion type with this underlying type
                NullableConverter nullableConverter = new NullableConverter(conversionType);
                conversionType = nullableConverter.UnderlyingType;
            } // end if
            if (value is string && conversionType == typeof(Guid))
            {
                return new Guid(value.ToString());
            }

            // Now that we've guaranteed conversionType is something Convert.ChangeType can handle (i.e. not a
            // nullable type), pass the call on to Convert.ChangeType
            return Convert.ChangeType(value, conversionType);
        }


        ///// <summary>
        ///// Helper method to serialize an object to a byte array
        ///// </summary>
        ///// <param name="value"></param>
        ///// <returns></returns>
        //public static byte[] SerializeMe(object value)
        //{
        //    //Serialize product to BSON
        //    var ms = new MemoryStream();
        //    var writer = new Newtonsoft.Json.Bson.BsonWriter(ms);
        //    var serializer = new JsonSerializer();
        //    serializer.PreserveReferencesHandling = PreserveReferencesHandling.All;
        //    serializer.Serialize(writer, value);

        //    ms.Close();
        //    writer.Close();

        //    return ms.ToArray();
        //}

        ///// <summary>
        ///// Helper method to deserialize a byte array to an object of type T
        ///// </summary>
        ///// <typeparam name="T"></typeparam>
        ///// <param name="value"></param>
        ///// <returns></returns>
        //public static T DeserializeMe<T>(byte[] value)
        //{
        //    var serializer = new JsonSerializer();
        //    serializer.PreserveReferencesHandling = PreserveReferencesHandling.All;
        //    var reader = new Newtonsoft.Json.Bson.BsonReader(new MemoryStream(value));
        //    var returnObj = serializer.Deserialize<T>(reader);

        //    reader.Close();

        //    return returnObj;
        //}




        public static Control FindControl(this Form frm, string Name)
        {
            FieldInfo propInfo;
            propInfo = frm.GetType().GetField(Name, (BindingFlags.IgnoreCase
                            | (BindingFlags.Instance
                            | (BindingFlags.NonPublic | BindingFlags.Public))));
            if (!(propInfo == null))
            {
                object value = propInfo.GetValue(frm);
                if (typeof(Control).IsAssignableFrom(value.GetType()))
                {
                    return ((Control)(value));
                }
            }
            return null;
        }

        //public static void SetFormValues(this Form frm, object values)
        //{
        //    PropertyInfo[] fieldInfoArray = typeof(Setting).GetProperties(
        //   BindingFlags.Instance | BindingFlags.Public |
        //   BindingFlags.SetProperty | BindingFlags.DeclaredOnly);
        //    foreach (PropertyInfo fieldInfo in fieldInfoArray)
        //    {
        //        Control ctl = frm.FindControl(fieldInfo.Name);
        //        TextBox txt = ctl as TextBox;
        //        if (txt != null)
        //        {
        //            try
        //            {
        //                object sourceFieldValue = fieldInfo.GetValue(values, null);
        //                var txtProp = typeof(TextBox).GetProperty("Text");
        //                txtProp.SetValue(txt, sourceFieldValue.ToString(), null);
        //            }
        //            catch (System.Exception ex)
        //            {
        //            }
        //        }
        //    }
        //}

        //public static T GetValues<T>(this Form frm, T applyToObject) where T : new()
        //{
        //    if (applyToObject == null)
        //    {
        //        applyToObject = new T();
        //    }
        //    PropertyInfo[] fieldInfoArray = typeof(Setting).GetProperties(
        //              BindingFlags.Instance | BindingFlags.Public |
        //              BindingFlags.SetProperty | BindingFlags.DeclaredOnly);

        //    foreach (PropertyInfo fieldInfo in fieldInfoArray)
        //    {
        //        Control ctl = frm.FindControl(fieldInfo.Name);
        //        TextBox txt = ctl as TextBox;
        //        if (txt != null)
        //        {
        //            if (fieldInfo.PropertyType.IsValueType || fieldInfo.PropertyType == typeof(string))
        //            {
        //                try
        //                {
        //                    object sourceFieldValue = txt.Text.ChangeType(fieldInfo.PropertyType);
        //                    fieldInfo.SetValue(applyToObject, sourceFieldValue, null);
        //                }
        //                catch (System.Exception ex)
        //                {
        //                }
        //            }
        //        }
        //    }
        //    return applyToObject;
        //}



    }



}
